from dataclasses import dataclass, field
from typing import Generic, TypeVar, Optional, List, Sequence

from pydantic import BaseModel, Field

from app.enums.error import ErrorCodeEnum

T = TypeVar("T")


@dataclass
class ApiResult(Generic[T]):
    """ API返回结果 """

    # 状态码
    code: int
    # 状态信息
    message: str
    # 返回数据
    data: T = None
    # 错误信息
    error: Optional[str] = None
    # 是否成功
    success: Optional[bool] = field(init=False)

    def __post_init__(self):
        """
        dataclass初始化后自动调用的方法

        根据状态码判断请求是否成功，当状态码等于成功状态码时标记为成功
        """
        self.success = self.code == ErrorCodeEnum.SUCCESS.code

    @staticmethod
    def result(code, message, data=None, error=None):
        """
        返回结果

        :param code: 状态码
        :param message: 提示信息
        :param data: 数据
        :param error: 错误信息
        :return: ApiResult
        """
        return ApiResult(code, message, data, error)

    @staticmethod
    def ok(
        code: int = ErrorCodeEnum.SUCCESS.code,
        message: str = ErrorCodeEnum.SUCCESS.message,
        data=None,
        error=None
    ):
        """
        成功返回结果

        :param code: 状态码
        :param message: 提示信息
        :param data: 数据
        :param error: 错误信息
        :return: ApiResult
        """
        return ApiResult.result(code, message, data, error)

    @staticmethod
    def fail(
        code: int = ErrorCodeEnum.FAIL.code,
        message: str = ErrorCodeEnum.FAIL.message,
        data=None,
        error=None
    ):
        """
        失败返回结果

        :param code: 状态码
        :param message: 提示信息
        :param data: 数据
        :param error: 错误信息
        :return: ApiResult
        """
        return ApiResult.result(code, message, data, error)


class PageResult(BaseModel, Generic[T]):
    """ 分页结果 """
    # 当前页数据
    list: List[T] | Sequence[T]
    # 总数量
    count: Optional[int]


class PageParam(BaseModel, Generic[T]):
    """ 分页参数 """
    # 当前页
    page: int = Field(1, ge=1, description="页码不能小于1")
    # 每页显示条数
    limit: int = Field(10, ge=1, le=100, description="每页数量应在1-100之间")
    # 查询条件
    model: T | None
    # 排序字段
    sort: Optional[str] = None
    # 排序规则
    order: Optional[str] = None

